package com.hooya.fa.eu.biz.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.hooya.fa.eu.api.bo.check.TempKcjlBO;
import com.hooya.fa.eu.api.util.DateExtUtil;
import com.hooya.fa.eu.biz.dao.entity.CkDict;
import com.hooya.fa.eu.biz.dao.entity.dto.StockQtyDTO;
import com.hooya.fa.eu.biz.dao.entity.dto.StockQtyDTO;
import com.hooya.fa.eu.biz.dao.entity.dto.StoreCorpDTO;
import com.hooya.fa.eu.biz.dao.mapper.CkDictMapper;
import com.hooya.fa.eu.biz.dao.mapper.MetaStoreMapper;
import com.hooya.fa.eu.biz.dao.mapper.TempKcjlDailyMapper;
import com.hooya.fa.eu.biz.dao.mapper.Xsjl2303Mapper;
import com.hooya.fa.eu.biz.dao.mapper.stk.StkOrigCollectMapper;
import com.hooya.fa.eu.biz.service.EuCheckService;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 1
 * @Author : Zongz
 * @Copyright Copyright (c) 豪雅集团
 * @Create 2024/11/14
 * @Version 1.1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EuCheckServiceImpl implements EuCheckService {

	private final TempKcjlDailyMapper tempKcjlDailyMapper;

	private final StkOrigCollectMapper stkOrigCollectMapper;

	private final MetaStoreMapper metaStoreMapper;

	private final Xsjl2303Mapper Xsjl2303Mapper;

	private final CkDictMapper ckDictMapper;

	@Override
	public void checkAndContrastKcjl(String endDate) {
		LocalDate parse = LocalDate.parse(endDate);
		String date = DateExtUtil.getBeforeNMonthLastDay(parse, 1);
		List<TempKcjlBO> list = tempKcjlDailyMapper.checkAndContrastKcjl(date);
		if (!CollectionUtils.isEmpty(list)) {
			XxlJobHelper.log("存在差异。" + list);
			log.error("kcjl校验失败,差异信息{}",list);
			//TODO -- 后续取消注释
//			throw new RuntimeException("kcjl校验失败");
		}
	}

	@Override
	public void checkAndContrastKcjl() {
		LocalDate now = LocalDate.now();
		String date = DateExtUtil.getBeforeNMonthLastDay(now, 1);
		List<TempKcjlBO> list = tempKcjlDailyMapper.checkAndContrastKcjl(date);
		if (!CollectionUtils.isEmpty(list)) {
			// TODO -- 待try catch
			XxlJobHelper.log("存在差异。" + list);
		}
	}

	@Override
	public void checkAndContrastStockList(String beginDate) {
		String startDate = beginDate; // 2025-08-01
		String endDate = DateExtUtil.getAfterNDays(1, beginDate); // 2025-08-02
		List<String> sheetNumber = stkOrigCollectMapper.checkRepeatSheetNumberDaily(startDate, endDate);
		if (!CollectionUtils.isEmpty(sheetNumber)) {
			// TODO -- 做记录，并且报错终止进程
			log.error("sheetNumber在历史中存在{}", sheetNumber);
			XxlJobHelper.log("sheetNumber在历史中存在" + sheetNumber);
			throw new RuntimeException("sheetNumber在历史种存在");
		}
	}

	@Override
	public void checkAndContrastStockList() {
		StringBuffer sb = new StringBuffer();
		LocalDate now = LocalDate.now();
		String startDate = DateExtUtil.getBeforeNMonthFirstDay(now, 1);
		String endDate = DateExtUtil.getBeforeNMonthLastDay(now, 1);
		List<String> sheetNumber = stkOrigCollectMapper.checkRepeatSheetNumber(startDate, endDate);
		if (!CollectionUtils.isEmpty(sheetNumber)) {
			// TODO -- 做记录，并且报错终止进程
			XxlJobHelper.log("sheetNumber在历史种存在" + sheetNumber);
		}
		int sl = stkOrigCollectMapper.checkTempAndStkSl(startDate, endDate);
		if (sl != 0) {
			// TODO -- 数据条数对不上，报错终止
			XxlJobHelper.log(sl > 0 ? "temp数据存在多次执行/数据不一致情况，请核查" : "temp数据存在漏执行情况/数据不一致情况，请核查");
		}
	}

	@Override
	public void checkAndInsertCkDict() {
		//     加载fa_eu.meta_store,得到所有的 店铺-公司 映射数据 （store-corp）
		Map<String, String> storeCorpDic = new HashMap<>();
		List<StoreCorpDTO> storeCorpList = metaStoreMapper.getStoreAndCorp();
		if (!CollectionUtil.isEmpty(storeCorpList)) {
			for (StoreCorpDTO dto : storeCorpList) {
				if (dto.getStore() != null && dto.getCorp() != null) {
					storeCorpDic.put(dto.getStore(), dto.getCorp());
				}
			}
			log.info("成功加载了 {} 条店铺-公司映射数据, 映射数据如：{}", storeCorpDic.size(), storeCorpDic);
		} else log.info("当月/当天没有店铺数据/没有店铺-公司映射数据");

		// 测试是否有新店铺
		List<String> stores = Xsjl2303Mapper.getStores();

		// 创建一个集合，用于存储现有店铺
		Set<String> existStoreLower = new HashSet<>();
		//用于存储新店铺----就是stores不存在于existStoreLower中的集合
		List<String> newStores = new ArrayList<>();

		// 将现有店铺转为小写存入集合
		for (String store : storeCorpDic.keySet()) {
			existStoreLower.add(store.toLowerCase());
		}

		// 检查新店铺
		for (String store : stores) {
			if (store != null && !existStoreLower.contains(store.toLowerCase())) {
				newStores.add(store);
				// TODO -- 这些新增店铺，应该是会存储在某一个表中的 -- 确实会存，这一步是由黄金沐来处理的，一般不会出现，但是出现后需上报
				//  TODO -- 如果有新增的店铺，该怎么办-- 目前是直接抛异常--进行中断执行--然后上报（黄金沐），当数据库填写完毕后，再次执行即可
			}
		}

		if (!newStores.isEmpty()) {
			log.error("新增店铺数量： {} , 新增店铺列表: {}", newStores.size(), newStores);
			// TODO -- 目前的解决方法，就是中断运行，人工处理，处理完成后，再次手动运行
			// TODO -- 后续放开这个异常
//			throw new RuntimeException("出现新增店铺，中断运行");
		} else {
			log.info("当月/当天没有新增的店铺");
		}
		log.info("测试新店铺通过");

		// 测试是否有新oeu订单
		// 查询OEU订单
		List<String> oeuOrderIds = Xsjl2303Mapper.getOeuIds();

		// 从数据库获取oeuOrderMap字典
		List<CkDict> oeuOrderDictList = ckDictMapper.selectByName("oeuOrderMap");

		//通过oeuOrderDictList--组成键值对象
		Map<String, String> oeuOrderMap = new HashMap<>();
		for (CkDict dict : oeuOrderDictList) {
			oeuOrderMap.put(dict.getParamKey(), dict.getParamValue());
		}

		// 创建一个集合，用于存储新增订单
		List<String> newOeuOrders = new ArrayList<>();
		// 检查订单是否存在
		for (String orderId : oeuOrderIds) {
			if (orderId != null && !oeuOrderMap.containsKey(orderId)) {
				newOeuOrders.add(orderId);
				// TODO -- 这些新增订单的订单号，应该是会存储在某一个字典表中 -- 确实会存，这一步是由邵璐露露来处理的，一般不会出现，但是出现后需上报
				// TODO -- 得到这些新增订单后，如何做 -- 目前是直接抛异常--进行中断执行--然后上报（邵露露）让其添加，当数据库填写完毕后，再次执行即可
			}
		}

		if (!newOeuOrders.isEmpty()) {
			log.error("新增oeu订单集合: {}", newOeuOrders);
			// TODO -- 目前的解决方法，就是中断运行，人工处理，处理完成后，再次手动运行
			// TODO -- 后续放开这个异常
//			throw new RuntimeException("出现新增oeu订单，中断运行");
		} else {
			log.info("当月/当天没有oeu订单");
		}

		log.info("测试OEU订单通过");

	}

	@Override
	public void checkStockQty(String beginDate) {

		try {
			// 处理日期
			String nextDay = DateExtUtil.getAfterNDays(1,beginDate); // 2025-08-02 (当前天的后一天)
			String preMonthEnd = DateExtUtil.getBeforeNDays(1, beginDate); // 2025-07-31 (当前天的前一天)
			String curMonthEnd = beginDate; // (当前天 = beginDate)

			// 获取库存变化
			List<StockQtyDTO> qtyChanges = stkOrigCollectMapper.getQtyChanges(beginDate, nextDay);
			// 获取期初和期末库存
			List<StockQtyDTO> beginQty = tempKcjlDailyMapper.getBeginQty(preMonthEnd);
			List<StockQtyDTO> endQty = tempKcjlDailyMapper.getEndQty(curMonthEnd);

			Map<String, List<StockQtyDTO>> beginQtyMap = beginQty.stream().collect(Collectors.groupingBy(f -> f.getSku() + "|" + f.getWhid()));
			List<StockQtyDTO> addBegin = new ArrayList<>();
			for (StockQtyDTO mainItem : qtyChanges) {
				String key = mainItem.getSku() + "|" + mainItem.getWhid();
				if (beginQtyMap.containsKey(key)) {
					List<StockQtyDTO> StockQtyDTOS = beginQtyMap.get(key);
					StockQtyDTOS.forEach(f -> {
						StockQtyDTO newItem = new StockQtyDTO();
						BeanUtils.copyProperties(mainItem, newItem);
						newItem.setBeginqty(f.getBeginqty());
						addBegin.add(newItem);
					});
				} else {
					addBegin.add(mainItem);
				}
			}


			Map<String, List<StockQtyDTO>> endQtyMap = endQty.stream().collect(Collectors.groupingBy(f -> f.getSku() + "|" + f.getWhid()));
			List<StockQtyDTO> addEnd = new ArrayList<>();
			for (StockQtyDTO mainItem : addBegin) {
				String key = mainItem.getSku() + "|" + mainItem.getWhid();
				if (endQtyMap.containsKey(key)) {
					List<StockQtyDTO> StockQtyDTOS = endQtyMap.get(key);
					StockQtyDTOS.forEach(f -> {
						StockQtyDTO newItem = new StockQtyDTO();
						BeanUtils.copyProperties(mainItem, newItem);
						newItem.setEndqty(f.getEndqty());
						addEnd.add(newItem);
					});
				} else {
					addEnd.add(mainItem);
				}
			}


			// 计算差值
			for (StockQtyDTO data : addEnd) {
				data.setDifference(data.getEndqty() - data.getBeginqty());
			}
			// 检查差异----收集异常数据/差值不为0
			List<StockQtyDTO> mismatched = addEnd.stream()
					.filter(data -> data.getDifferqty() - data.getDifference() != 0)
					.collect(Collectors.toList());
			if (!mismatched.isEmpty()) {
				log.error("发现库存变化量有不一致的记录，数量: {} 条 ， 数据为{}", mismatched.size(), mismatched);
				log.error("异常数据：{}", mismatched);
                throw new RuntimeException("库存变化不一致，数量: " + mismatched.size());
			}
			log.info("库存变化一致性检查通过");
		} catch (Exception e) {
			log.error("库存变化一致性检查失败", e);
            throw new RuntimeException("库存变化一致性检查失败", e);
		}

	}

}
